import datetime
from django.shortcuts import render
from utils.mixin_utils import LoginRequiredMixin
from django.views.generic.base import View
from payroll.models import *
from django.http.response import HttpResponseRedirect, HttpResponse, JsonResponse  # ajax返回数据
from utils.check_permission import check_custom_perms
import requests
from salary.settings import BASE_DIR, Corpid_, payroll_Scret, payroll_uri
import os
from utils.pd_excel import PreCondition
from django.utils.http import urlquote


# 首页视图，后期可填充数据报表，做dasbord
class Index(LoginRequiredMixin, View):
    def get(self, request):
        uid = request.user.id
        perms = check_custom_perms(10, uid, "read")
        if not perms:
            return render(request, 'deny.html')
        # 获取统计数据
        data = SentIndex.objects.all().order_by('-time')
        return render(request, 'payroll/index.html', {'data': data})


# 工资条基础设置（管理员）
class BaseSettingView(LoginRequiredMixin, View):
    def get(self, request):
        uid = request.user.id
        perms = check_custom_perms(13, uid, "read")
        if not perms:
            return render(request, 'deny.html')
        # 1,获取基础数据
        basic_data = BasicInfo.objects.filter(id=1).all()
        if not basic_data:
            # 保存初始数据
            default_ = BasicInfo(name_colom=11, title_start=2, title_end=3, phone_colom=12)
            default_.save()
            # 重新获取数据
            basic_data = BasicInfo.objects.filter(id=1).all()

        return render(request, "payroll/base_setting.html", {"data": basic_data})

    def post(self, request):
        uid = request.user.id
        perms = check_custom_perms(13, uid, "change")
        if not perms:
            return render(request, 'deny.html')
        # 标题开始行
        title_start = int(request.POST.get('title_start'))
        # 标题结束行
        title_end = int(request.POST.get('title_end'))
        # 姓名列
        name_colom = int(request.POST.get('name_colom'))
        # 联系人
        contact = request.POST.get('contact')
        # 实发金额列
        total_money_colom = request.POST.get("total_money_colom")
        # 电话所在列
        phone_colom = request.POST.get("phone_colom")
        # 企业名称
        company_name = request.POST.get("company_name")
        # 企业微信联系人
        wechat_admin = request.POST.get("wechat_admin")

        # 更新到数据库
        data = BasicInfo.objects.get(id=1)
        data.title_start = title_start
        data.title_end = title_end
        data.name_colom = name_colom
        data.contact = contact
        data.total_money_colom = total_money_colom
        data.phone_colom = phone_colom
        data.company_name = company_name
        data.wechat_admin = wechat_admin
        data.save()
        return JsonResponse({"status": 1, "info": "修改成功！"})


# 2，上传工资表，开启预览
class UploadAndPreView(LoginRequiredMixin, View):
    def get(self, request):
        uid = request.user.id
        perms = check_custom_perms(10, uid, "read")
        if not perms:
            return render(request, 'deny.html')
        # 默认发送时间为当月，当年
        cur_year = datetime.datetime.now().year
        cur_month = datetime.datetime.now().month
        return render(request, "payroll/upload_salary_file.html", {"send_year": cur_year, "send_month": cur_month})

    def post(self, request):
        uid = request.user.id
        perms = check_custom_perms(10, uid, "change")
        if not perms:
            return render(request, 'deny.html')
        # 发送渠道
        send_way = request.POST.getlist("send_way")
        # xlsx文件
        xlsx_content_type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
        # 补发的年
        bufa_year = request.POST.get('bufa_year')
        # 补发的月
        bufa_month = request.POST.get('bufa_month')
        # 发送的年月[不存数据库，用于工资条标题]
        set_send_year = request.POST.get("send_year")
        set_send_month = request.POST.get("send_month")
        # 工资表文件
        salary_file = request.FILES.get('salary_file')
        # 3，整合邮件主题[根据前端返回的年月]
        if not bufa_year and not bufa_month:
            # 不是补发
            subject = str(set_send_year) + "年" + str(set_send_month) + "月工资条"
            paymonth = str(set_send_year) + "-" + str(set_send_month) + "-01"
        else:
            # 是补发
            subject = "【补发】" + str(bufa_year) + "年" + str(bufa_month) + "月工资条"
            paymonth = str(bufa_year) + "-" + str(bufa_month) + "-01"
        # 保存文件
        if salary_file:
            if str(salary_file.content_type) != xlsx_content_type:
                return HttpResponse("您选择的文件不是.xlsx格式的excel文件！")
            else:
                # 上传工资表
                path = open(os.path.join(BASE_DIR, 'static', 'upload', 'payroll', str(salary_file)), 'wb+')
                for chunk in salary_file:
                    path.write(chunk)
                path.close()
                # 文件保存成功，获取基础信息
                data = BasicInfo.objects.get(id=1)
                # 1,整合标题行
                title_row = [data.title_start, data.title_end]
                # 2,首先是预览模式
                how = 0
                # 3, 预览模式，无需制作url
                url = "no"
                msg = PreCondition(str(salary_file), title_row, data.name_colom, data.contact, how, paymonth,
                                   data.phone_colom,
                                   data.total_money_colom, data.company_name, subject, send_way, url)

                # 检查是否正确返回了预览数据
                if msg["status"] == 2:
                    # 渲染预览表单
                    return render(request, 'payroll/preshow.html', {'data': msg["data"],
                                                                    'salary_file': str(salary_file),
                                                                    'send_way': send_way, 'subject': subject,
                                                                    "send_year": set_send_year,
                                                                    "send_month": set_send_month,
                                                                    "paymonth": paymonth,
                                                                    })
                else:
                    return HttpResponse("预览出错，请联系管理员处理！")
        else:
            return HttpResponse("文件读取错误，请确认是否已选工资表！")


# 预览界面点击确认发送后，进行工资条发送操作
class SendPayrollView(LoginRequiredMixin, View):
    def post(self, request):
        # 1,从前端获取发送数据
        # 1.1, 工资表文件名
        salary_file = request.POST.get("salary_file")
        # 1.2 发送方式
        send_way = request.POST.get("send_way")
        # 1.3 主题
        subject = request.POST.get("subject")
        # 1.4 发送的年月
        set_send_year = request.POST.get("send_year")
        set_send_month = request.POST.get("send_month")
        # 1.5 发送年月
        paymonth = request.POST.get("paymonth")
        # 2, 从数据库获取基本信息
        data = BasicInfo.objects.get(id=1)
        title_row = [data.title_start, data.title_end]
        # 2,定义操作方式为直接发送
        how = 1
        # 3, 预览模式，无需制作url
        url = payroll_uri + "payroll/redirect/" + str(set_send_year) + "/" + str(set_send_month)

        # 避免后台等待太久，采用线程发送方式发送
        # 预览通过，那么数据格式不会有问题，可以直接发送
        """
        import threading
        threading.Thread(target=PreCondition, args=(str(salary_file), title_row, data.name_colom, data.contact, how,
                                                    paymonth, data.phone_colom, data.total_money_colom,
                                                    data.company_name, subject, send_way, url)).start()
        return JsonResponse({'status': 1, 'info': '任务已成功提交，稍后将跳转结果显示界面，若结果显示不全，可稍后再刷新查看！'})
        """
        msg = PreCondition(str(salary_file), title_row, data.name_colom, data.contact, how,
                           paymonth, data.phone_colom, data.total_money_colom,
                           data.company_name, subject, send_way, url)
        # 检测返回值
        if msg["status"] == 0:
            # 发送出错
            return JsonResponse({"status": 0, "info": msg["errmsg"]})
        else:
            # 处理完成，发送成功
            info = "处理完成！本次合计处理：" + str(msg["total_count"]) + "条，其中成功：" + str(msg["valid_count"]) + \
                   "条，忽略了：" + str(msg["ignore_count"]) + "条。 "
            return JsonResponse({"status": 1, "info": info})


# 查看所有的发送历史记录，通过导航条进入
class SentHistoryView(LoginRequiredMixin, View):
    def get(self, request):
        uid = request.user.id
        perms = check_custom_perms(11, uid, "read")
        if not perms:
            return render(request, 'deny.html')
        SentInfo = SentContents.objects.all().order_by('-time')
        return render(request, 'payroll/success.html', {'SentInfo': SentInfo})


# 查询某一次发送批次的全部记录，通过点击首页的批次进入
class SingleHistoryView(LoginRequiredMixin, View):
    def get(self, request):
        uid = request.user.id
        perms = check_custom_perms(12, uid, "read")
        if not perms:
            return render(request, 'deny.html')
        mark_id = request.GET.get('mark_id')
        SentInfo = SentContents.objects.filter(mark_id=mark_id).order_by('-time')
        return render(request, 'payroll/success.html', {'SentInfo': SentInfo})


# 工资条确认【用户点击邮件链接进行确认】
class ConfirmSalaryView(View):
    def get(self, request):
        confirm = request.GET.get('code')
        from_ = request.GET.get("f")
        # 判断传入的数据的有效性，避免误打误撞被攻击
        if confirm and len(confirm) == 45:
            if SentContents.objects.filter(confirm=confirm):
                # 数据正确,将状态改为已确认
                SentContents.objects.filter(confirm=confirm).update(confirm='1')
                if from_ == "ent_wechat":
                    # 来自企业微信的确认
                    return JsonResponse({"status": 1, "info": "确认成功！"})
                else:
                    return render(request, 'payroll/confirm.html', {'status': 1, 'info': '确认成功！'})
            else:
                if from_ == "ent_wechat":
                    # 来自企业微信的确认
                    return JsonResponse({"status": 0, "info": "不可重复确认！"})
                else:
                    return render(request, 'payroll/confirm.html', {'status': 0, 'info': '不可重复确认！'})
        else:
            if from_ == "ent_wechat":
                # 来自企业微信的确认
                return JsonResponse({"status": 2, "info": "非法访问！"})
            else:
                return render(request, 'payroll/confirm.html', {'status': 2, 'info': '非法访问！'})


class ShowPayRollInEntWechat(View):
    def get(self, request, year, month, mark_id):
        # 此链接为企业微信跳转而来，会返回用户ID
        # 1, 获取Code
        code = request.GET.get("code")
        if code:
            # 2，获取access_token
            def GetToken(Corpid, Secret):
                Url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"
                Data = {
                    "corpid": Corpid,
                    "corpsecret": Secret
                }
                r = requests.get(url=Url, params=Data)
                if r.json()["errmsg"] == "ok":
                    Token = r.json()['access_token']
                else:
                    Token = ''
                return Token

            # 2.2 获取用户信息
            def GetUserId(token_, code_):
                Url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo"
                Data = {
                    "access_token": token_,
                    "code": code_
                }
                r = requests.get(url=Url, params=Data)
                if r.json()["errmsg"] == "ok":
                    # 请求成功
                    user_id = r.json()["UserId"]
                else:
                    user_id = ""
                return user_id

            # 2.3 获取用户的姓名和手机号码
            def getUserInfo(token_, uid):
                Url = "https://qyapi.weixin.qq.com/cgi-bin/user/get"
                Data = {
                    "access_token": token_,
                    "userid": uid
                }
                r = requests.get(url=Url, params=Data)
                return r.json()

            # 开始操作
            Token = GetToken(Corpid_, payroll_Scret)
            if Token != "":
                uid = GetUserId(Token, code)

                if uid != "":
                    # 获取用户信息
                    user_data = getUserInfo(Token, uid)
                    if user_data['errmsg'] == "ok":
                        # 请求成功
                        name = user_data['name']
                        mobile = user_data['mobile']
                        # 匹配数据库的数据
                        # 获取公司名称
                        base_data = BasicInfo.objects.get(id=1)
                        company_name = base_data.company_name
                        if year == month == "none":
                            # 未传入请求的年月，则默认展现汇总列表
                            data = SentContents.objects.filter(username=name, userphone=mobile).all().order_by("-id")
                            return render(request, 'payroll/ent_wechat_list.html', {"data": data,
                                                                                    'company_name': company_name})
                        else:
                            # 传入了年月，则展现详情页
                            if str(mark_id) == "None":
                                data = SentContents.objects.filter(username=name, userphone=mobile,
                                                                   pay_month__month=month,
                                                                   pay_month__year=year).all()
                            else:
                                data = SentContents.objects.filter(username=name, userphone=mobile,
                                                                   pay_month__month=month,
                                                                   pay_month__year=year, mark_id=mark_id).all()
                            if data:
                                total_money = data[0].total_money
                                contents = data[0].contents
                                nan = ""  # pandas 处理excel数据的时候会将空值定义为nan，转字典之前要定义一个空值，不然转字典会失败
                                contents = eval(contents)  # 转字典
                                # 验证状态
                                if data[0].confirm == "1":
                                    # 已确认
                                    confirm_url = "1"
                                else:
                                    code = data[0].confirm
                                    from salary.settings import confirm_uri
                                    confirm_url = confirm_uri + "?code=" + code
                                wechat_admin = BasicInfo.objects.get(id=1)
                                wechat_admin = wechat_admin.wechat_admin
                                return render(request, 'payroll/ent_wechat_detail.html',
                                              {"data": contents, 'year': year,
                                               "month": month, 'total_money': total_money,
                                               'company_name': company_name,
                                               "confirm_url": confirm_url,
                                               "mark_id": mark_id,
                                               "wechat_admin": wechat_admin,
                                               })
                            else:
                                return HttpResponse("查看明细数据获取错误，请联系管理员！")

                    else:
                        return HttpResponse("用户信息获取失败，请联系管理员！错误：" + user_data["errmsg"])
                else:
                    return HttpResponse("用户ID获取失败，请联系管理员！")
            else:
                return HttpResponse("Token获取失败，请联系管理员！")
        else:
            return HttpResponse("此应用仅允许在企业微信内部打开！")


# 企业微信应用卡片消息跳转URL
class Redirect(View):
    def get(self, request, year, month, mark_id, t):
        # 企业微信工资条跳转URL
        if t == "wechat":
            # 企业微信跳转
            redirect_url = payroll_uri + "payroll/ent_wechat/" + str(year) + "/" + str(month) + "/" + str(mark_id)
        else:
            # 其他跳转
            redirect_url = payroll_uri + "payroll/ent_wechat/" + str(year) + "/" + str(month) + "/" + str(mark_id)
        redirect_url = urlquote(redirect_url)
        url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww778513745cdbfe07&redirect_uri=%s" \
              "&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect""" % (
                  redirect_url)
        return HttpResponseRedirect(url)
